/*
 * Copyright (C) 2010-2012 Geometer Plus <contact@geometerplus.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package cn.dns.reader.network;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.text.TextUtils;
import android.widget.RemoteViews;
import android.widget.Toast;
import cn.dns.zlibrary.core.network.ZLNetworkException;
import cn.dns.zlibrary.core.network.ZLNetworkManager;
import cn.dns.zlibrary.core.network.ZLNetworkRequest;

import com.hctforgreen.greenservice.R;
import com.hctforgreen.greenservice.ctr.DbController;
import com.hctforgreen.greenservice.ctr.HctController;
import com.hctforgreen.greenservice.db.DBVideoDownloadManager;
import com.hctforgreen.greenservice.model.BookListEntity.BookEntity;
import com.hctforgreen.greenservice.model.ResultEntity;
import com.hctforgreen.greenservice.model.VideoTypeEntity.VideoDetailEntity.VideoPartEntity;
import com.hctforgreen.greenservice.service.HctApplication;
import com.hctforgreen.greenservice.utils.EntryCatalogUtil;
import com.hctforgreen.greenservice.utils.HctConstants;
import com.hctforgreen.greenservice.utils.HctResult;
import com.mato.sdk.proxy.Address;

public class VideoDownloaderService extends Service {
	public static final String SHOW_NOTIFICATIONS_KEY = "org.geometerplus.android.fbreader.network.ShowNotifications";

	public static final String TITLE_KEY = "org.geometerplus.android.fbreader.network.Title";
	public static final String BOOK_FORMAT_KEY = "org.geometerplus.android.fbreader.network.BookFormat";

	private Address address;

	public interface Notifications {
		int DOWNLOADING_STARTED = 0x0001;
		int ALREADY_DOWNLOADING = 0x0002;

		int ALL = 0x0003;
	}

	private Set<VideoPartEntity> mDownloadingUrls = Collections
			.synchronizedSet(new HashSet<VideoPartEntity>());

	/**
	 * 等待下载队列
	 */
	private List<VideoPartEntity> mWaitingUrls = Collections
			.synchronizedList(new ArrayList<VideoPartEntity>());

	private Set<Integer> myOngoingNotifications = new HashSet<Integer>();

	private volatile int myServiceCounter;

	private void doStart() {
		++myServiceCounter;
	}

	private void doStop() {
		if (--myServiceCounter == 0) {
			stopSelf();
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return new BookDownloaderInterface.Stub() {
			public boolean isBeingDownloaded(String url) {
				if (contains(url)) {
					return true;
				} else {
					return false;
				}

			}

			@Override
			public boolean hasDownloadingUrl() throws RemoteException {
				if (mDownloadingUrls.size() > 0) {
					return true;
				}
				return false;
			}

			@Override
			public boolean cancelDownloadingUrl(String url)
					throws RemoteException {
				for (VideoPartEntity entity : mDownloadingUrls) {
					if (entity.videoUrl.equals(url)) {
						entity.downloadState = HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ALREADY_CANCEL;
						return true;
					}
				}
				Iterator<VideoPartEntity> keys = mWaitingUrls.iterator();
				VideoPartEntity key = null;
				while (keys.hasNext()) {
					key = (VideoPartEntity) keys.next();
					if (key.videoUrl.equals(url)) {
						keys.remove();
						return true;
					}
				}
				return false;
			}
		};
	}

	@Override
	public void onDestroy() {
		final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		for (int notificationId : myOngoingNotifications) {
			notificationManager.cancel(notificationId);
			clearDownloadingURLs(notificationManager, notificationId);
		}
		myOngoingNotifications.clear();

		super.onDestroy();
	}

	/**
	 * 在下载Service销毁时，如果还有没有下载完成的，设置为下载失败状态
	 * 
	 * @param notificationId
	 */
	private void clearDownloadingURLs(NotificationManager notificationManager,
			int notificationId) {

		for (VideoPartEntity bookEntity : mDownloadingUrls) {
			if (bookEntity == null) {
				return;
			}
			if (bookEntity.notificationId == notificationId) {
				if (bookEntity.doWhatClick
						.equals(HctConstants.ON_ACTIVITY_KEY_DO_UPDATE_CLICK)) {
					updateBookProgress(bookEntity, 100);
					updateBookZipState(
							bookEntity,
							HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ANALISIS_DONE);
					sendDownloadedProgressBroadcast(bookEntity.id, true, 100);
				} else {
					updateBookProgress(bookEntity, 0);
					updateBookZipState(
							bookEntity,
							HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_DOWNLOAD_FAIL);
					sendDownloadedProgressBroadcast(bookEntity.id, true, 0);
				}

				remove(bookEntity.videoUrl);
				String title = bookEntity.videoName;

				notificationManager.notify(
						notificationId,
						createDownloadFinishNotification(title, 0, bookEntity,
								notificationId));
			}
		}
	}

	@Override
	public void onStart(Intent intent, int startId) {
		super.onStart(intent, startId);

		doStart();

		if (intent == null) {
			doStop();
			return;
		}
		final Uri uri = intent.getData();
		if (uri == null) {
			doStop();
			return;
		}
		intent.setData(null);

		final int notifications = intent.getIntExtra(SHOW_NOTIFICATIONS_KEY, 0);

		final String url = uri.toString();
		final String bookFormat = intent.getStringExtra(BOOK_FORMAT_KEY);

		VideoPartEntity bookEntity = (VideoPartEntity) intent
				.getSerializableExtra(HctConstants.ON_ACTIVITY_KEY_BOOK_ENTITY);

		String address = intent.getStringExtra("address.host");
		int port = intent.getIntExtra("address.port", -11);
		if (!TextUtils.isEmpty(address)) {
			try {
				this.address = new Address(address, port);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		String cleanURL = bookEntity.videoUrl;
		if (cleanURL == null) {
			cleanURL = url;
		}

		if (contains(url)) {
			if ((notifications & Notifications.ALREADY_DOWNLOADING) != 0) {

				Toast.makeText(getApplicationContext(),
						getString(R.string.already_downloading),
						Toast.LENGTH_SHORT).show();
			}
			doStop();
			return;
		}

		String fileName = VideoPartEntity.makeVideoFileName(bookEntity,
				getApplicationContext());
		if (fileName == null) {
			doStop();
			return;
		}

		int index = fileName.lastIndexOf(File.separator);
		if (index != -1) {
			final String dir = fileName.substring(0, index);
			final File dirFile = new File(dir);
			if (!dirFile.exists() && !dirFile.mkdirs()) {

				Toast.makeText(
						getApplicationContext(),
						getString(R.string.cannot_create_directory).replace(
								"%s", dirFile.getPath()), Toast.LENGTH_SHORT)
						.show();
				doStop();
				return;
			}
			if (!dirFile.exists() || !dirFile.isDirectory()) {
				Toast.makeText(
						getApplicationContext(),
						getString(R.string.cannot_create_directory).replace(
								"%s", dirFile.getPath()), Toast.LENGTH_SHORT)
						.show();
				doStop();
				return;
			}
		}

		final File fileFile = new File(fileName);
		if (fileFile.exists()) {
			if (!fileFile.isFile()) {

				Toast.makeText(
						getApplicationContext(),
						getString(R.string.cannot_create_file).replace("%s",
								fileFile.getPath()), Toast.LENGTH_SHORT).show();
				doStop();
				return;
			}

			// doStop();
			/**
			 * TODO:点击已经存在文件的下载链接会去调用阅读器的功能
			 */
			// startActivity(getStartEntryCatalogIntent(bookEntity));
			// return;
		}
		String title = intent.getStringExtra(TITLE_KEY);
		if (title == null || title.length() == 0) {
			title = fileFile.getName();
		}

		if (mDownloadingUrls.size() < 3) {
			if ((notifications & Notifications.DOWNLOADING_STARTED) != 0) {

				Toast.makeText(getApplicationContext(),
						getString(R.string.downloading_started),
						Toast.LENGTH_SHORT).show();
			}
			// Util.tryToDeleteBookZip(bookEntity, getApplicationContext());
			startFileDownload(bookEntity, "", fileFile, title);
			// addDownloadCount(getApplicationContext(), bookEntity.bookName);
		} else {

			mWaitingUrls.add(bookEntity);
			updateBookZipState(
					bookEntity,
					HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_DOWNLOAD_WAITING);
			sendDownloadedProgressBroadcast(bookEntity.id, true, -1);
			doStop();
		}

	}

	private boolean addDownloadFromWaitingUrls() {
		if (mDownloadingUrls.size() < 3 && mWaitingUrls.size() > 0) {

			Iterator<VideoPartEntity> keys = mWaitingUrls.iterator();
			if (keys.hasNext()) {
				VideoPartEntity key = (VideoPartEntity) keys.next();
				keys.remove();
				String fileName = VideoPartEntity.makeVideoFileName(key,
						getApplicationContext());
				final File file = new File(fileName);

				// Util.tryToDeleteBookZip(key, getApplicationContext());

				startFileDownload(key, "", file, key.videoName);
				// addDownloadCount(getApplicationContext(), key.bookName);
			}
			return true;
		}
		return false;
	}

	private void addDownloadCount(final Context context, final String bookName) {

		final Handler handler = new Handler() {
			public void handleMessage(Message msg) {

				HctResult hctResult = new HctResult();
				switch (msg.what) {
				case HctConstants.STATUS_SUCCESS:

					hctResult = (HctResult) msg.obj;

					ResultEntity entity = (ResultEntity) hctResult.data;

					break;

				case HctConstants.STATUS_FAILD:

					break;
				}
			}

		};
		new Thread() {
			public void run() {
				Message message = new Message();
				try {
					HctController controller = new HctController(context);

					HctResult result = controller.addDownloadCount(context,
							bookName);
					if (result.status == HctConstants.STATUS_SUCCESS) {
						message.what = result.status;
						message.obj = result;
					} else {
						message.what = HctConstants.STATUS_FAILD;
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				handler.sendMessage(message);
			}
		}.start();
	}

	private Notification createDownloadCancelNotification(File file,
			String title) {
		final String tickerText = getApplicationContext().getString(
				R.string.download_cancel_hint);
		final String contentText = getApplicationContext().getString(
				R.string.download_cancel_hint);
//		final Notification notification = new Notification(
//				android.R.drawable.stat_sys_download_done, tickerText,
//				System.currentTimeMillis());
//		notification.flags |= Notification.FLAG_AUTO_CANCEL;

		final Intent intent = new Intent();
		final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				intent, 0);
//		notification.setLatestEventInfo(getApplicationContext(), title,
//				contentText, contentIntent);
		//390697 20161201 兼容6.0
		Notification.Builder notificationBuilder=new Notification.Builder(getApplicationContext());
		Notification notification = notificationBuilder.setContentTitle(title)
				.setContentText(contentText)
				.setSmallIcon(android.R.drawable.stat_sys_download_done)
				.setContentIntent(contentIntent)
				.build();
		notification.flags |= Notification.FLAG_AUTO_CANCEL ;
		return notification;
	}

	/**
	 * 
	 * @param title
	 * @param what
	 *            0:失败,1:成功,2:解析失败
	 * @return
	 */
	private Notification createDownloadFinishNotification(String title,
			int what, VideoPartEntity bookEntity, final int notificationId) {
		final String tickerText = getTickerText(what);
		final String contentText = getContentText(what);
//		final Notification notification = new Notification(
//				android.R.drawable.stat_sys_download_done, tickerText,
//				System.currentTimeMillis());
//		notification.flags |= Notification.FLAG_AUTO_CANCEL;

		// final Intent intent = (what == 1)?
		// getStartEntryCatalogIntent(bookEntity):new Intent();
		final Intent intent = new Intent();
		final PendingIntent contentIntent = PendingIntent.getActivity(this,
				notificationId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
//		notification.setLatestEventInfo(getApplicationContext(), title,
//				contentText, contentIntent);

		//390697 20161201 兼容6.0
		Notification.Builder notificationBuilder=new Notification.Builder(getApplicationContext());
		Notification notification = notificationBuilder.setContentTitle(title)
				.setContentText(contentText)
				.setSmallIcon(android.R.drawable.stat_sys_download_done)
				.setContentIntent(contentIntent)
				.build();
		notification.flags |= Notification.FLAG_AUTO_CANCEL ;
		return notification;
	}

	private Intent getStartEntryCatalogIntent(final BookEntity entity) {
		EntryCatalogUtil catalogUtil = new EntryCatalogUtil();
		Intent intent = catalogUtil.getStartEntryCatalogIntent(
				getApplicationContext(), entity);
		return intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
				| Intent.FLAG_ACTIVITY_NEW_TASK);
	}

	private String getContentText(int what) {
		String contentText = "";
		if (what == 0) {
			contentText = getString(R.string.content_error);
		} else if (what == 1) {
			contentText = getString(R.string.content_success);
		} else if (what == 2) {
			contentText = getString(R.string.book_zip_txt_error_hint);
		}
		return contentText;
	}

	private String getTickerText(int what) {
		String tickerText = "";
		if (what == 0) {
			tickerText = getString(R.string.ticker_error);
		} else if (what == 1) {
			tickerText = getString(R.string.ticker_success);
		} else if (what == 2) {
			tickerText = getString(R.string.book_zip_txt_error_hint);
		}

		return tickerText;
	}

	private Notification createDownloadProgressNotification(String title) {
		final RemoteViews contentView = new RemoteViews(getPackageName(),
				R.layout.download_notification);
		contentView.setTextViewText(R.id.download_notification_title, title);
		contentView.setTextViewText(R.id.download_notification_progress_text,
				"");
		contentView.setProgressBar(R.id.download_notification_progress_bar,
				100, 0, true);

		final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(), 0);

		final Notification notification = new Notification();
		notification.icon = android.R.drawable.stat_sys_download;
		notification.flags |= Notification.FLAG_ONGOING_EVENT;
		notification.contentView = contentView;
		notification.contentIntent = contentIntent;

		return notification;
	}

	private Notification createAnalisisingNotification(String title) {
		final String contentText = getApplicationContext().getString(
				R.string.analysis_ing_hint);

		final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
				new Intent(), 0);

//		final Notification notification = new Notification();
//		notification.icon = android.R.drawable.stat_sys_download;
//		notification.flags |= Notification.FLAG_ONGOING_EVENT;
//		notification.contentIntent = contentIntent;

//		notification.setLatestEventInfo(getApplicationContext(), title,
//				contentText, contentIntent);
		//390697 20161201 兼容6.0
		Notification.Builder notificationBuilder=new Notification.Builder(getApplicationContext());
		Notification notification = notificationBuilder.setContentTitle(title)
				.setContentText(contentText)
				.setSmallIcon(android.R.drawable.stat_sys_download)
				.setContentIntent(contentIntent)
				.build();
		notification.flags |= Notification.FLAG_ONGOING_EVENT ;
		return notification;
	}

	/**
	 * 更新进度
	 */
	private void updateBookProgress(final VideoPartEntity bookEntity,
			final int progress) {

		HctApplication application = (HctApplication) getApplication();
		DbController dbController = new DbController(application.getDbAdapter());
		bookEntity.progress = progress;
		// dbController.updateBookProgress(bookEntity);
	}

	/**
	 * 更新状态
	 */
	private void updateBookZipState(final VideoPartEntity bookEntity,
			final String state) {
		HctApplication application = (HctApplication) getApplication();
		DBVideoDownloadManager dbVideoDownloadManager = new DBVideoDownloadManager(
				getApplicationContext());
		bookEntity.downloadState = state;
		dbVideoDownloadManager.updatepartEntity(bookEntity);
		// dbController.updateBookZipState(bookEntity);

		Intent intent = new Intent();
		intent.setAction(HctConstants.RECEIVER_VIDEOSHELF_ACTIVITY_DOWNLOAD_UPDATE_PARTS);
		sendBroadcast(intent);

	}

	private void updateBookCannotUpdateState(final VideoPartEntity bookEntity) {

		HctApplication application = (HctApplication) getApplication();
		DbController dbController = new DbController(application.getDbAdapter());

		BookEntity inDbEntity = dbController.getBookEntity(bookEntity.id);
		// if (inDbEntity.versionCode.equals(bookEntity.versionCode)) {
		// dbController.updateBookBCannotUpdate(bookEntity);
		// }

	}

	private void startFileDownload(final VideoPartEntity bookEntity,
			final String sslCertificate, final File file, final String title) {
		final String urlString = bookEntity.videoUrl;
		add(urlString);

		final int notificationId = NetworkNotifications.Instance()
				.getBookDownloadingId();
		final Notification progressNotification = createDownloadProgressNotification(title);

		final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		myOngoingNotifications.add(Integer.valueOf(notificationId));
		notificationManager.notify(notificationId, progressNotification);

		final Handler progressHandler = new Handler() {
			public void handleMessage(Message message) {
				final int progress = message.what;
				if (!downloadingUrlsContains(urlString)) {
					return;
				}
				updateBookProgress(bookEntity, progress);

				updateBookZipState(
						bookEntity,
						HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_DOWNLOAD_ING);

				sendDownloadedProgressBroadcast(bookEntity.id, false, progress);
				final RemoteViews contentView = (RemoteViews) progressNotification.contentView;

				if (progress < 0) {
					contentView.setTextViewText(
							R.id.download_notification_progress_text, "");
					contentView.setProgressBar(
							R.id.download_notification_progress_bar, 100, 0,
							true);
				} else {
					contentView.setTextViewText(
							R.id.download_notification_progress_text, ""
									+ progress + "%");
					contentView.setProgressBar(
							R.id.download_notification_progress_bar, 100,
							progress, false);
				}
				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager
						.notify(notificationId, progressNotification);
			}

		};

		final Handler downloadFinishHandler = new Handler() {
			public void handleMessage(Message message) {
				if (!downloadingUrlsContains(urlString)) {
					return;
				}
				if (message.what == 1) {
					updateBookProgress(bookEntity, 100);
					updateBookZipState(
							bookEntity,
							HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_DOWNLOAD_DONE);
					updateBookCannotUpdateState(bookEntity);
					sendDownloadedProgressBroadcast(bookEntity.id, true, 100);
				} else if (message.what == 0 || message.what == 2) {

					if (bookEntity.doWhatClick == null
							|| bookEntity.doWhatClick
									.equals(HctConstants.ON_ACTIVITY_KEY_DO_UPDATE_CLICK)) {
						updateBookProgress(bookEntity, 100);
						updateBookZipState(
								bookEntity,
								HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_DOWNLOAD_FAIL);
						sendDownloadedProgressBroadcast(bookEntity.id, true, 0);

					} else {
						updateBookProgress(bookEntity, 0);
						updateBookZipState(
								bookEntity,
								HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_DOWNLOAD_FAIL);
						sendDownloadedProgressBroadcast(bookEntity.id, true, 0);
					}

				}

				remove(urlString);
				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager.cancel(notificationId);
				myOngoingNotifications.remove(Integer.valueOf(notificationId));
				notificationManager.notify(
						notificationId,
						createDownloadFinishNotification(title, message.what,
								bookEntity, notificationId));

				if (!addDownloadFromWaitingUrls()) {
					doStop();
				}
			}
		};
		final Handler analisisIngHandler = new Handler() {
			public void handleMessage(Message message) {

				if (!downloadingUrlsContains(urlString)) {

					return;
				}
				updateBookZipState(
						bookEntity,
						HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ANALISIS_ING);

				updateBookProgress(bookEntity, 100);

				sendDownloadedProgressBroadcast(bookEntity.id, true, 100);

				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager.cancel(notificationId);
				myOngoingNotifications.remove(Integer.valueOf(notificationId));
				notificationManager.notify(notificationId,
						createAnalisisingNotification(title));
				doAnalysis(bookEntity, downloadFinishHandler);
			}
		};

		final Handler downloadCancelHandler = new Handler() {
			public void handleMessage(Message message) {

				// if (bookEntity.doWhatClick
				// .equals(HctConstants.ON_ACTIVITY_KEY_DO_UPDATE_CLICK)) {
				// updateBookProgress(bookEntity, 100);
				// updateBookZipState(
				// bookEntity,
				// HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ANALISIS_DONE);
				// sendDownloadedProgressBroadcast(bookEntity.download_url,
				// true, 100);
				// } else {
				// updateBookProgress(bookEntity, 0);
				// updateBookZipState(
				// bookEntity,
				// HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ALREADY_CANCEL);
				// sendDownloadedProgressBroadcast(bookEntity.download_url,
				// true, 0);
				// }
				remove(urlString);
				final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
				notificationManager.cancel(notificationId);
				myOngoingNotifications.remove(Integer.valueOf(notificationId));
				notificationManager.notify(notificationId,
						createDownloadCancelNotification(file, title));
				if (!addDownloadFromWaitingUrls()) {
					doStop();
				}
			}
		};
		final ZLNetworkRequest request = new ZLNetworkRequest(urlString,
				sslCertificate, null) {
			public void handleStream(InputStream inputStream, int length)
					throws IOException, ZLNetworkException {
				/**
				 * 刷新间隔
				 */
				final int updateIntervalMillis = 2000;

				int downloadedPart = 0;
				long progressTime = System.currentTimeMillis()
						+ updateIntervalMillis;
				if (length <= 0) {
					progressHandler.sendEmptyMessage(-1);
				}
				OutputStream outStream;
				try {
					outStream = new FileOutputStream(file);
				} catch (FileNotFoundException ex) {
					throw new ZLNetworkException(
							ZLNetworkException.ERROR_CREATE_FILE,
							file.getPath());
				}
				try {
					final byte[] buffer = new byte[7168];
					while (!isCancel(urlString)) {
						final int size = inputStream.read(buffer);

						if (size <= 0) {
							break;
						}
						downloadedPart += size;

						if (length > 0) {
							final long currentTime = System.currentTimeMillis();
							if (currentTime > progressTime) {
								progressTime = currentTime
										+ updateIntervalMillis;

								float fPart = Float.valueOf(downloadedPart)
										* 100f / Float.valueOf(length);
								progressHandler.sendEmptyMessage((int) fPart);

							}
							/*
							 * if (downloadedPart * 100 / length > 95) { throw
							 * new IOException("debug exception"); }
							 */
						}
						outStream.write(buffer, 0, size);
						/*
						 * try { Thread.currentThread().sleep(200); } catch
						 * (InterruptedException ex) { }
						 */
					}

					if (isCancel(urlString)) {
						downloadCancelHandler.sendEmptyMessage(0);
					}
				} finally {

					inputStream.close();
					outStream.close();
				}
			}
		};

		final Thread downloader = new Thread(new Runnable() {
			public void run() {
				boolean success = false;
				try {
					ZLNetworkManager.Instance().perform(request, address);
					success = true;
				} catch (ZLNetworkException e) {
					e.printStackTrace();
					file.delete();
				} finally {
					if (!downloadingUrlsContains(urlString)) {
						return;
					}
					if (success) {
						analisisIngHandler.sendEmptyMessage(success ? 1 : 0);
					} else if (!success) {
						downloadFinishHandler.sendEmptyMessage(0);
					}

				}
			}
		});
		downloader.setPriority(Thread.MIN_PRIORITY);
		downloader.start();
	}

	/**
	 * 发送下载进度的广播
	 * 
	 * @param url
	 * @param progress
	 */
	private void sendDownloadedProgressBroadcast(String url, boolean isSwitch,
			int progress) {

		/**
		 * 发送广播
		 */
		Intent intent = new Intent();
		intent.setAction(HctConstants.RECEIVER_VIDEOSHELF_ACTIVITY_DOWNLOAD_UPDATE);
		intent.putExtra(HctConstants.ON_DOWNLOAD_SERIVE_KEY_DOWNLOAD_URL, url);
		intent.putExtra(
				HctConstants.ON_DOWNLOAD_SERIVE_KEY_SWITCH_DOWNLOAD_STATE,
				isSwitch);
		intent.putExtra(HctConstants.ON_DOWNLOAD_SERIVE_KEY_PROGRESS, progress);

		sendBroadcast(intent);

	}

	private boolean contains(String url) {
		if (downloadingUrlsContains(url) || waitingUrlsContains(url)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * XXX
	 * 
	 * @param bean
	 */
	private boolean downloadingUrlsContains(String url) {
		for (VideoPartEntity entity : mDownloadingUrls) {
			if (entity.videoUrl.equals(url)) {
				return true;
			}
		}
		return false;
	}

	private boolean waitingUrlsContains(String url) {
		for (VideoPartEntity entity : mWaitingUrls) {
			if (entity.videoUrl.equals(url)) {
				return true;
			}
		}
		return false;
	}

	private void add(String url) {
		VideoPartEntity entity = new VideoPartEntity();
		entity.videoUrl = url;
		mDownloadingUrls.add(entity);
	}

	private void remove(String url) {
		Iterator<VideoPartEntity> keys = mDownloadingUrls.iterator();
		VideoPartEntity key = null;
		while (keys.hasNext()) {
			key = (VideoPartEntity) keys.next();
			if (key.videoUrl.equals(url)) {
				keys.remove();
			}
		}
	}

	private boolean isCancel(String url) {
		CopyOnWriteArraySet<VideoPartEntity> copySets = new CopyOnWriteArraySet<VideoPartEntity>();
		copySets.addAll(mDownloadingUrls);

		for (VideoPartEntity entity : copySets) {
			if (entity.videoUrl.equals(url)
					&& HctConstants.ON_ACTIVITY_KEY_BOOK_ZIP_STATE_ALREADY_CANCEL
							.equals(entity.downloadState)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 下载完成
	 */
	private void doAnalysis(final VideoPartEntity bookEntity,
			final Handler downloadFinishHandler) {

		// String local = VideoPartEntity.makeVideoFileName(bookEntity,
		// getApplicationContext());
		downloadFinishHandler.sendEmptyMessage(1);
	}

}
